package org.esti.model.dao.impl;

import org.esti.model.Book;
import org.esti.model.KnowledgeField;
import org.esti.model.User;
import org.esti.model.dao.BookDAO;
import org.esti.model.exceptions.BookDoesNotExistException;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.util.List;

/**
 * @author Artem Loginov (logart)
 */
@Repository
public class BookDAOimpl implements BookDAO {

    @PersistenceContext
    private EntityManager entityManager;

    /**
     * {@inheritDoc}
     */
    @Transactional(readOnly = true, noRollbackFor = BookDoesNotExistException.class)
    @Override
    public Book getBookById(long id) {
        Book book = entityManager.find(Book.class, id);
        if (book == null) {
            throw new BookDoesNotExistException();
        } else {
            return book;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Transactional(readOnly = true)
    @Override
    public List<Book> getUsersBooks(User user) {
        try {
            Query query = entityManager.createQuery("SELECT b FROM Book b WHERE b.publisher=:user");
            query.setParameter("user", user);
            return (List<Book>) query.getResultList();
        } catch (NoResultException ex) {
            throw new BookDoesNotExistException(ex);
        }

    }

    /**
     * {@inheritDoc}
     */
    @Transactional(readOnly = true)
    @Override
    public List<Book> getKnowledgeFieldBooks(KnowledgeField knowledgeFieldId) {
        try {
            Query query = entityManager.createQuery("SELECT b FROM Book b WHERE b.knowledgeField=:knowledgeField");
            query.setParameter("knowledgeField", knowledgeFieldId);
            return (List<Book>) query.getResultList();
        } catch (NoResultException ex) {
            throw new BookDoesNotExistException(ex);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Transactional
    @Override
    public Book update(Book book) {
        return entityManager.merge(book);
    }

    /**
     * {@inheritDoc}
     */
    @Transactional
    @Override
    public void deleteBook(Book book) {
        Book bookx = entityManager.find(Book.class, book.getId());
        entityManager.remove(bookx);
    }

    /**
     * {@inheritDoc}
     */
    @Transactional(readOnly = true)
    @Override
    public List<Book> getAllBooks() {
        return (List<Book>) entityManager.createQuery("SELECT b FROM Book b").getResultList();
    }
}
